package ums_user_repo

import (
	"fmt"
	"github.com/pkg/errors"
	"gorm.io/gorm"
	"time"
	"web/app/dao/db_repo"
)

func NewModel() *UmsUser {
	return new(UmsUser)
}

func NewQueryBuilder() *umsUserRepoQueryBuilder {
	return new(umsUserRepoQueryBuilder)
}

func (t *UmsUser) Create(db *gorm.DB) (id interface{}, err error) {
	if err = db.Create(t).Error; err != nil {
		return 0, errors.Wrap(err, "create err")
	}
	return t.Id, nil
}

type umsUserRepoQueryBuilder struct {
	order []string
	where []struct {
		prefix string
		value  interface{}
	}
	limit  int
	offset int
}

func (qb *umsUserRepoQueryBuilder) buildQuery(db *gorm.DB) *gorm.DB {
	ret := db
	for _, where := range qb.where {
		ret = ret.Where(where.prefix, where.value)
	}
	for _, order := range qb.order {
		ret = ret.Order(order)
	}
	ret = ret.Limit(qb.limit).Offset(qb.offset)
	return ret
}

func (qb *umsUserRepoQueryBuilder) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
	db = db.Model(&UmsUser{})

	for _, where := range qb.where {
		db.Where(where.prefix, where.value)
	}

	if err = db.Updates(m).Error; err != nil {
		return errors.Wrap(err, "updates err")
	}
	return nil
}

func (qb *umsUserRepoQueryBuilder) Delete(db *gorm.DB) (err error) {
	for _, where := range qb.where {
		db = db.Where(where.prefix, where.value)
	}

	if err = db.Delete(&UmsUser{}).Error; err != nil {
		return errors.Wrap(err, "delete err")
	}
	return nil
}

func (qb *umsUserRepoQueryBuilder) Count(db *gorm.DB) (int64, error) {
	var c int64
	res := qb.buildQuery(db).Model(&UmsUser{}).Count(&c)
	if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
		c = 0
	}
	return c, res.Error
}

func (qb *umsUserRepoQueryBuilder) First(db *gorm.DB) (*UmsUser, error) {
	ret := &UmsUser{}
	res := qb.buildQuery(db).First(ret)
	if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
		ret = nil
	}
	return ret, res.Error
}

func (qb *umsUserRepoQueryBuilder) QueryOne(db *gorm.DB) (*UmsUser, error) {
	qb.limit = 1
	ret, err := qb.QueryAll(db)
	if len(ret) > 0 {
		return ret[0], err
	}
	return nil, err
}

func (qb *umsUserRepoQueryBuilder) QueryAll(db *gorm.DB) ([]*UmsUser, error) {
	var ret []*UmsUser
	err := qb.buildQuery(db).Find(&ret).Error
	return ret, err
}

func (qb *umsUserRepoQueryBuilder) Limit(limit int) *umsUserRepoQueryBuilder {
	qb.limit = limit
	return qb
}

func (qb *umsUserRepoQueryBuilder) Offset(offset int) *umsUserRepoQueryBuilder {
	qb.offset = offset
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereId(p db_repo.Predicate, value int64) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "id", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereIdIn(value []int64) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "id", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereIdNotIn(value []int64) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "id", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderById(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "id "+order)
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereTenantId(p db_repo.Predicate, value int64) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "tenant_id", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereTenantIdIn(value []int64) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "tenant_id", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereTenantIdNotIn(value []int64) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "tenant_id", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderByTenantId(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "tenant_id "+order)
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereUsername(p db_repo.Predicate, value string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "username", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereUsernameIn(value []string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "username", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereUsernameNotIn(value []string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "username", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderByUsername(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "username "+order)
	return qb
}

func (qb *umsUserRepoQueryBuilder) WherePassword(p db_repo.Predicate, value string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "password", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WherePasswordIn(value []string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "password", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WherePasswordNotIn(value []string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "password", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderByPassword(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "password "+order)
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereGender(p db_repo.Predicate, value int32) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "gender", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereGenderIn(value []int32) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "gender", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereGenderNotIn(value []int32) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "gender", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderByGender(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "gender "+order)
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereEmail(p db_repo.Predicate, value string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "email", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereEmailIn(value []string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "email", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereEmailNotIn(value []string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "email", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderByEmail(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "email "+order)
	return qb
}

func (qb *umsUserRepoQueryBuilder) WherePhone(p db_repo.Predicate, value string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "phone", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WherePhoneIn(value []string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "phone", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WherePhoneNotIn(value []string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "phone", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderByPhone(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "phone "+order)
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereAvatar(p db_repo.Predicate, value string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "avatar", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereAvatarIn(value []string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "avatar", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereAvatarNotIn(value []string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "avatar", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderByAvatar(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "avatar "+order)
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereCreatedAt(p db_repo.Predicate, value time.Time) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "created_at", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereCreatedAtIn(value []time.Time) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "created_at", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereCreatedAtNotIn(value []time.Time) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "created_at", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderByCreatedAt(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "created_at "+order)
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereUpdatedAt(p db_repo.Predicate, value time.Time) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "updated_at", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereUpdatedAtIn(value []time.Time) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "updated_at", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereUpdatedAtNotIn(value []time.Time) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "updated_at", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderByUpdatedAt(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "updated_at "+order)
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereDeletedAt(p db_repo.Predicate, value time.Time) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "deleted_at", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereDeletedAtIn(value []time.Time) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "deleted_at", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereDeletedAtNotIn(value []time.Time) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "deleted_at", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderByDeletedAt(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "deleted_at "+order)
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereOrderNum(p db_repo.Predicate, value int32) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "order_num", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereOrderNumIn(value []int32) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "order_num", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereOrderNumNotIn(value []int32) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "order_num", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderByOrderNum(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "order_num "+order)
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereAccountId(p db_repo.Predicate, value int64) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "account_id", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereAccountIdIn(value []int64) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "account_id", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereAccountIdNotIn(value []int64) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "account_id", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderByAccountId(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "account_id "+order)
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereIsAdmin(p db_repo.Predicate, value int32) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "is_admin", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereIsAdminIn(value []int32) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "is_admin", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereIsAdminNotIn(value []int32) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "is_admin", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderByIsAdmin(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "is_admin "+order)
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereName(p db_repo.Predicate, value string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "name", p),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereNameIn(value []string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "name", "IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) WhereNameNotIn(value []string) *umsUserRepoQueryBuilder {
	qb.where = append(qb.where, struct {
		prefix string
		value  interface{}
	}{
		fmt.Sprintf("%v %v ?", "name", "NOT IN"),
		value,
	})
	return qb
}

func (qb *umsUserRepoQueryBuilder) OrderByName(asc bool) *umsUserRepoQueryBuilder {
	order := "DESC"
	if asc {
		order = "ASC"
	}

	qb.order = append(qb.order, "name "+order)
	return qb
}
